package com.bkhc.product.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bkhc.common.entity.Lookup;
import com.bkhc.common.repository.LookupRepository;
import com.bkhc.common.to.ProductPriceTo;
import com.bkhc.common.util.CommonUtil;
import com.bkhc.common.util.IdWorker;
import com.bkhc.common.util.TransObject;
import com.bkhc.common.util.response.PageUtil;
import com.bkhc.common.util.response.ResultCode;
import com.bkhc.common.util.response.ResultJson;
import com.bkhc.common.vo.BrandPriceVo;
import com.bkhc.common.vo.UserBean;
import com.bkhc.product.entity.*;
import com.bkhc.product.repository.*;
import com.bkhc.product.strategy.CalculatePriceService;
import com.bkhc.product.strategy.RatioPriceStrategy;
import com.bkhc.product.vo.*;
import org.hibernate.SQLQuery;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Transactional
public class PriceService {

    @Autowired
    private PriceRuleRepository priceRuleRepository;
    @Autowired
    private BrandGoodsRepository brandGoodsRepository;
    @Autowired
    private BrandGoodPriceRepository brandGoodPriceRepository;
    @Autowired
    private GoodsRepository goodsRepository;
    @PersistenceContext
    private EntityManager entityManager;
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private BrandRepository brandRepository;
    @Autowired
    private GoodspecRepository goodspecRepository;
    @Autowired
    private LookupRepository lookupRepository;
    @Autowired
    private BuessinesRepository buessinesRepository;


    public ResultJson<?> calculatePrice(BrandProduct brandProduct) {
        //品牌下产品规则
        List<PriceRule> rules = priceRuleRepository.findByProductCodeAndBrandCode(brandProduct.getProductCode(), brandProduct.getBrandCode());
        Map<String, PriceRule> ruleMap = rules.stream().collect(Collectors.toMap(PriceRule::getIndentity, priceRule -> priceRule));
        //品牌下产品商品
        List<BrandGoods> brandgoods = brandGoodsRepository.findByProductCodeAndBrandCode(brandProduct.getProductCode(), brandProduct.getBrandCode());
        List<String> brandAllGoods = brandgoods.stream().map(BrandGoods::getGoodsCode).collect(Collectors.toList());
        //所有商业身份
        List<BrandGoodPrice> brandAllGoodPrices = brandGoodPriceRepository.findByBrandCodeAndGoodsCodeList(brandProduct.getBrandCode(), brandAllGoods);
        List<Lookup> lookupItems = lookupRepository.findByItemClass("Indentity");
        if (!CollectionUtils.isEmpty(brandgoods)) {
            for (BrandGoods goods : brandgoods) {
                List<BrandGoodPrice> brandGoodPrices = brandAllGoodPrices.stream().filter(x->x.getGoodsCode().equals(goods.getGoodsCode())).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(brandGoodPrices)) {
                    brandGoodPrices = new ArrayList<>();
                    //如何价格是第一次写入，则进行初始化，初始化厂商和固定价格
                    for (Lookup item : lookupItems) {
                        BrandGoodPrice bgp = new BrandGoodPrice();
                        bgp.setProductCode(brandProduct.getProductCode());
                        bgp.setGoodsCode(goods.getGoodsCode());
                        bgp.setBrandCode(brandProduct.getBrandCode());
                        bgp.setIndentity(item.getItemCode());
                        bgp.setStatus("1");
                        PriceRule priceRule = ruleMap.get(item.getItemCode());
                        if(priceRule == null ){
                            continue;
                        }
                        if ("1".equals(priceRule.getRelateWay())) {
                            bgp.setPrice(new BigDecimal(0));
                        }
                        if ("2".equals(priceRule.getRelateWay())) {
                            bgp.setPrice(new BigDecimal(0));
                        }
                        if ("3".equals(priceRule.getRelateWay())) {
                            String fixprice = priceRule.getFixPrice();
                            JSONObject json = JSONObject.parseObject(fixprice);
                            Object price = json.get(goods.getGoodsCode());
                            if (price instanceof BigDecimal) {
                                bgp.setPrice((BigDecimal) price);
                            }
                            if (price instanceof Integer) {
                                bgp.setPrice(new BigDecimal((Integer) price));
                            }
                        }

                        brandGoodPrices.add(bgp);
                    }
                    brandGoodPriceRepository.saveAll(brandGoodPrices);
                } else {
                    final Map<String, BrandGoodPrice> brandGoodPricesMap = brandGoodPrices.stream().collect(Collectors.toMap(BrandGoodPrice::getIndentity, brandGoodPrice -> brandGoodPrice));
                    final Map<String, List<PriceRule>> listMap = rules.stream().collect(Collectors.groupingBy(r -> r.getRelateWay()));
                    //厂商上传的规则
                    List<PriceRule> uploadRules = listMap.get("1");
                    if(!CollectionUtils.isEmpty(uploadRules)) {
                        for (PriceRule priceRule : uploadRules) {
                            BrandGoodPrice brandGoodPrice = brandGoodPricesMap.get(priceRule.getIndentity());
                            if (brandGoodPrice == null) {
                                BrandGoodPrice tem = new BrandGoodPrice();
                                tem.setProductCode(brandProduct.getProductCode());
                                tem.setGoodsCode(goods.getGoodsCode());
                                tem.setBrandCode(brandProduct.getBrandCode());
                                tem.setIndentity(priceRule.getIndentity());
                                tem.setStatus("1");
                                tem.setPrice(new BigDecimal(0));
                                brandGoodPricesMap.put(priceRule.getIndentity(), tem);
                            }
                        }
                    }
                    //固定值
                    List<PriceRule> fixRules = listMap.get("3");
                    if (!CollectionUtils.isEmpty(fixRules)) {
                        for (PriceRule fixRule : fixRules) {
                            BrandGoodPrice brandGoodPrice = brandGoodPricesMap.get(fixRule.getIndentity());
                            if (brandGoodPrice == null) {
                                brandGoodPrice = new BrandGoodPrice();
                                brandGoodPrice.setProductCode(brandProduct.getProductCode());
                                brandGoodPrice.setGoodsCode(goods.getGoodsCode());
                                brandGoodPrice.setBrandCode(brandProduct.getBrandCode());
                                brandGoodPrice.setIndentity(fixRule.getIndentity());
                                brandGoodPrice.setStatus("1");
                            }
                            String fixprice = fixRule.getFixPrice();
                            JSONObject json = JSONObject.parseObject(fixprice);
                            brandGoodPrice.setPrice(new BigDecimal(json.get(goods.getGoodsCode()) + ""));
                            brandGoodPricesMap.put(fixRule.getIndentity(), brandGoodPrice);
                        }

                    }
                    //比率
                    List<PriceRule> rateRules = listMap.get("2");
                    if (!CollectionUtils.isEmpty(rateRules)) {
                        for (PriceRule rateRule : rateRules) {
                            BrandGoodPrice relatebrandGoodPrice = brandGoodPricesMap.get(rateRule.getRelateObj());
                            BrandGoodPrice brandGoodPrice = brandGoodPricesMap.get(rateRule.getIndentity());
                            if (brandGoodPrice == null) {
                                brandGoodPrice = new BrandGoodPrice();
                                brandGoodPrice.setProductCode(brandProduct.getProductCode());
                                brandGoodPrice.setGoodsCode(goods.getGoodsCode());
                                brandGoodPrice.setBrandCode(brandProduct.getBrandCode());
                                brandGoodPrice.setIndentity(rateRule.getIndentity());
                                brandGoodPrice.setStatus("1");
                                BigDecimal price = relatebrandGoodPrice.getPrice().multiply(rateRule.getRate());
                                brandGoodPrice.setPrice(price);

                            }
                            BigDecimal price = relatebrandGoodPrice.getPrice().multiply(rateRule.getRate());
                            brandGoodPrice.setPrice(price);
                            brandGoodPricesMap.put(rateRule.getIndentity(), brandGoodPrice);

                        }

                    }


                    //增量加法
                    List<PriceRule> addPriceList = listMap.get("0");
                    if (!CollectionUtils.isEmpty(addPriceList)) {
                        addPriceList.forEach(priceRule -> {
                            BrandGoodPrice brandGoodPrice = brandGoodPricesMap.get(priceRule.getIndentity());
                            if (brandGoodPrice == null) {
                                brandGoodPrice = new BrandGoodPrice();
                                brandGoodPrice.setProductCode(brandProduct.getProductCode());
                                brandGoodPrice.setGoodsCode(goods.getGoodsCode());
                                brandGoodPrice.setBrandCode(brandProduct.getBrandCode());
                                brandGoodPrice.setIndentity(priceRule.getIndentity());
                                brandGoodPrice.setStatus("1");
                            }
                            String relateObject = priceRule.getRelateObj();
                            PriceRule rule = ruleMap.get(relateObject);
                            if("1".equals(rule.getRelateWay())){
                                BrandGoodPrice bg = brandGoodPricesMap.get(rule.getIndentity());
                                BigDecimal price =bg.getPrice().add(priceRule.getRate());
                                brandGoodPrice.setPrice(price);
                            }
                            if("3".equals(rule.getRelateWay())){
                                String fixprice = rule.getFixPrice();
                                JSONObject json = JSONObject.parseObject(fixprice);
                                BigDecimal price = new BigDecimal(json.get(goods.getGoodsCode()) + "").add(priceRule.getRate());
                                brandGoodPrice.setPrice(price);
                            }
                            brandGoodPricesMap.put(priceRule.getIndentity(), brandGoodPrice);
                        });
                    }
                    List<BrandGoodPrice> priceList = new ArrayList<>();
                    for (BrandGoodPrice object : brandGoodPricesMap.values()) {
                        priceList.add(object);
                    }
                    brandGoodPriceRepository.saveAll(priceList);
                }

            }

        }
        ResultJson<List<?>> resultJson = ResultJson.success();
        return resultJson;
    }


    public ResultJson<?> queryPriceByBrandProductSpec(BrandGoodsVO brandGoodsVO) {
        String productCode = brandGoodsVO.getProductCode();
        List<Goods> goodsList = goodsRepository.findByProductCode(productCode);

        StringBuffer sqlQuery = new StringBuffer();
        sqlQuery.append("select g.* from tbl_brand_goods g left join tbl_goods_t t on g.goods_code=t.goods_code where t.goods_code is not null and t.product_code='");
        sqlQuery.append(brandGoodsVO.getProductCode() + "'");
        sqlQuery.append("  and g.brand_code ='" + brandGoodsVO.getBrandCode() + "' ");

        for (SpecVO g : brandGoodsVO.getSpecs()) {
            if (StringUtils.isEmpty(g.getSpecValue())) {
                continue;
            }
            sqlQuery.append("and EXISTS (select * from tbl_goods_spec where");
            sqlQuery.append(" spec_code = '");
            sqlQuery.append(g.getSpecCode() + "'");
            sqlQuery.append(" and ");
            sqlQuery.append(" spec_value = '");
            sqlQuery.append(g.getSpecValue() + "'");
            sqlQuery.append(" and ");
            sqlQuery.append(" goods_code =t.goods_code)");
        }
        Query query = entityManager.createNativeQuery(sqlQuery.toString());
        query.unwrap(SQLQuery.class).setResultTransformer(new TransObject(BrandGoods.class));
        List<BrandGoods> list = query.getResultList();
        if (!CollectionUtils.isEmpty(list) && list.size() > 1) {
            ResultJson<List<?>> resultJson = ResultJson.success();
            return resultJson;
        }
        BrandGoods brandGoods = list.get(0);
        List<BrandGoodPrice> brandgoodsPrices = brandGoodPriceRepository.findByBrandCodeAndGoodsCode(brandGoods.getBrandCode(), brandGoods.getGoodsCode());
        ResultJson<List<BrandGoodPrice>> resultJson = ResultJson.success();
        UserBean user = CommonUtil.getCrruentUser();
        String indentity = "";
        if (user == null) {
            List<Lookup> indentityList = lookupRepository.findByItemClass("Indentity");
            Lookup defaultIndentity = indentityList.stream().filter(x -> "default".equals(x.getAttr1())).findFirst().get();
            indentity = defaultIndentity.getItemCode();
        } else {
            Map map = buessinesRepository.getCustomerIndentity(user.getUserId());
            indentity = (String) map.get("identity");
        }
        String finalIndentity = indentity;
        resultJson.setData(brandgoodsPrices.stream().filter(x -> finalIndentity.equals(x.getIndentity())).collect(Collectors.toList()));
        return resultJson;
    }

    public ResultJson<?> queryAllPriceByBrandProduct(String productCode, String brandCode) {
        StringBuffer sqlQuery = new StringBuffer();
        sqlQuery.append("SELECT g.goods_code as goodsCode,g.brand_code as brandCode,b.brand_name as brandName,g.product_code as productCode,p.product_name as productName FROM `tbl_brand_goods` g left join tbl_brand_t b on g.brand_code=b.brand_code\n" +
                "LEFT JOIN tbl_product_t p on g.product_code=p.product_code");
        sqlQuery.append(" where g.product_code='" + productCode + "' and g.brand_code='" + brandCode + "'");
        Query query = entityManager.createNativeQuery(sqlQuery.toString());
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(GoodsPriceVo.class));
        List<GoodsPriceVo> list = query.getResultList();
        packagePriceVo(list, productCode, brandCode,null);
        ResultJson<List<GoodsPriceVo>> resultJson = ResultJson.success();
        resultJson.setData(list);
        return resultJson;
    }

    public ResultJson<?> queryProductPrice(Map<String,String> paramMap, int pageIndex, int pageSize) {
        StringBuffer sqlQuery = new StringBuffer();
        String productCodes = paramMap.get("productCode");
        String priceType = paramMap.get("priceType");
        sqlQuery.append("SELECT g.goods_code as goodsCode,g.brand_code as brandCode,b.brand_name as brandName,g.product_code as productCode,p.product_name as productName FROM `tbl_brand_goods` g left join tbl_brand_t b on g.brand_code=b.brand_code\n" +
                "LEFT JOIN tbl_product_t p on g.product_code=p.product_code");
        sqlQuery.append(" where g.product_code in ('" + productCodes + "')");
        int start = (pageIndex - 1) * pageSize;
        sqlQuery.append(" limit ('" +start+","+pageSize+"')");
        Query query = entityManager.createNativeQuery(sqlQuery.toString());
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(GoodsPriceVo.class));
        List<GoodsPriceVo> list = query.getResultList();
        if (CollectionUtils.isEmpty(list)) {
            return ResultJson.success();
        }
        Map<String, List<GoodsPriceVo>> listMap = list.stream().collect(Collectors.groupingBy(GoodsPriceVo::getBrandCode));
        Set<String> keySet = listMap.keySet();
        List<ProductPriceTo> toList = new ArrayList<>();
        for (String brandCode : keySet) {
            List<GoodsPriceVo> goodsPriceVoList = listMap.get(brandCode);
            Map<String, List<GoodsPriceVo>> productCodeMap = goodsPriceVoList.stream().collect(Collectors.groupingBy(GoodsPriceVo::getProductCode));
            Set<String> productCodeSet = productCodeMap.keySet();
            for (String productCode : productCodeSet) {
                List<GoodsPriceVo> voList = productCodeMap.get(productCode);
                packagePriceVo(voList, productCode, brandCode,null);
                List<ProductPriceTo> productPriceToList = voList.stream().map(vo -> {
                    ProductPriceTo to = new ProductPriceTo();
                    to.setProductCode(productCode);
                    to.setGoodsCode(vo.getGoodsCode());
                    List<BrandGoodPrice> priceList = vo.getPriceList();
                    List<BrandPriceVo> brandPriceVoList = priceList.stream().map(priceVo -> {
                        BrandPriceVo brandPriceVo = new BrandPriceVo();
                        brandPriceVo.setPrice(priceVo.getPrice());
                        brandPriceVo.setBrandCode(priceVo.getBrandCode());
                        brandPriceVo.setBrandName(vo.getBrandName());
                        return brandPriceVo;
                    }).collect(Collectors.toList());
                    to.setBrandList(brandPriceVoList);
                    return to;
                }).collect(Collectors.toList());
                toList.addAll(productPriceToList);
            }
        }
        ResultJson<List<ProductPriceTo>> resultJson = ResultJson.success();
        resultJson.setData(toList);
        return resultJson;
    }


    private void packagePriceVo(List<GoodsPriceVo> list, String productCode, String brandCode,List<String> priceTypes) {
        List<BrandGoodPrice> brandgoodpriceList = brandGoodPriceRepository.findByProductCodeAndBrandCodeAndStatus(productCode, brandCode, "1");
        //TODO 待优化
        List<Lookup> lookupItems = new ArrayList<>();;
        if (StringUtils.isEmpty(priceTypes)){
            lookupItems = lookupRepository.findByItemClass("Indentity");
        }else{
            for(String itemCode:priceTypes){
                Lookup lookup = new Lookup();
                lookup.setItemCode(itemCode);
                lookupItems.add(lookup);
            }

        }
        List<String> goodsCodes = list.stream().map(GoodsPriceVo::getGoodsCode).collect(Collectors.toList());
        List<GoodsSpec> goodSpecs = goodspecRepository.findByGoodsCodeIn(goodsCodes);
        if (!CollectionUtils.isEmpty(list)) {
            for (GoodsPriceVo gp : list) {

                gp.setGoodsSpecList(goodSpecs.stream().filter(x->x.getGoodsCode().equals(gp.getGoodsCode())).collect(Collectors.toList()));
                ;
                List<BrandGoodPrice> priceList = brandgoodpriceList.stream().filter(x -> x.getGoodsCode().equals(gp.getGoodsCode())).collect(Collectors.toList());


                if (!CollectionUtils.isEmpty(priceList)) {

                    for (Lookup lookup : lookupItems) {
                        List<BrandGoodPrice> entitys = priceList.stream().filter(x -> x.getIndentity().equals(lookup.getItemCode())).collect(Collectors.toList());
                        if (CollectionUtils.isEmpty(entitys)) {
                            BrandGoodPrice bp = new BrandGoodPrice();
                            bp.setPrice(new BigDecimal(0));
                            bp.setIndentity(lookup.getItemCode());
                            bp.setGoodsCode(gp.getGoodsCode());
                            bp.setBrandCode(brandCode);
                            bp.setProductCode(productCode);
                            priceList.add(bp);
                        }
                    }
                } else {
                    priceList = new ArrayList<>();
                    for (Lookup lookup : lookupItems) {
                        BrandGoodPrice bp = new BrandGoodPrice();
                        bp.setPrice(new BigDecimal(0));
                        bp.setIndentity(lookup.getItemCode());
                        bp.setGoodsCode(gp.getGoodsCode());
                        bp.setBrandCode(brandCode);
                        bp.setProductCode(productCode);
                        priceList.add(bp);
                    }
                }
                gp.setPriceList(priceList);
            }
        }
    }

    public ResultJson<?> queryProductPriceByPriceAccount(List<BusinessPriceAccountVo> accountVoList) {
        StringBuffer sqlQuery = new StringBuffer();
        sqlQuery.append("SELECT g.goods_code as goodsCode,g.brand_code as brandCode,b.brand_name as brandName,g.product_code as productCode,p.product_name as productName FROM `tbl_brand_goods` g left join tbl_brand_t b on g.brand_code=b.brand_code\n" +
                "LEFT JOIN tbl_product_t p on g.product_code=p.product_code");
        List<GoodsPriceVo> totalList = new ArrayList<>();
        accountVoList.forEach(v->{
            sqlQuery.append(" where g.product_code='" + v.getProductCode() + "' and g.brand_code='" + v.getBrandCode() + "'");
            Query query = entityManager.createNativeQuery(sqlQuery.toString());
            query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(GoodsPriceVo.class));
            List<GoodsPriceVo> list = query.getResultList();
            packagePriceVo(list, v.getProductCode(), v.getBrandCode(),Arrays.asList(v.getIdentities().split(",")));
            totalList.addAll(list);
        });
        ResultJson<List<GoodsPriceVo>> resultJson = ResultJson.success();
        resultJson.setData(totalList);
        return resultJson;
    }
}
